<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | 文件管理控制器
// +----------------------------------------------------------------------

namespace july\julyadmin\admin\controller;

use july\julyadmin\builder\traits\HasBuilder;
use july\julyadmin\common\model\Files as FilesModel;

class Files extends Common
{
    use HasBuilder;

    //不需要登录验证的控制器和方法，如：['index']
    protected $noNeedLogin = [];
    //不需要权限验证的控制器和方法，如：['index']
    protected $noPermissionAuth = ['commonUploadForm'];

    public function __construct()
    {
        //重新初始化父类
        parent::initialize();
        //数据模型
        $this->dataModel = new FilesModel();
        //join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->relationWithJoins = ['filesCategory' => 'left'];
        //with预查询关联表信息，如category,comment
        $this->relationWiths = [];
        //页面标题
        $this->pageTitle = '文件管理';
        //允许表格行内编辑的字段,如name,sex
        $this->allowRowEditField = [];
        //不允许删除的主键数组，如1,2,3
        $this->noDeletePrimarykeys = [];
        //不允许编辑的主键数组，如1,2,3
        $this->noEditPrimarykeys = [];
        //不允许禁用的主键数组，如1,2,3
        $this->noDisabledPrimarykeys = [];
        //下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->selectRelationWithJoins = [];
        //下拉with预查询关联表信息，如category,comment
        $this->selectRelationWiths = [];
        //下拉列表默认查询条件，如 [['disabled', '=', 1]]，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectWhere = [];
        //下拉列表模糊查询字段,如 'name|title'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectSearch = '';
        //下拉列表默认 Text 字段 如 '{id}#{nickname}'或者'id:{id}-名称:{name}'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectTextField = '';
        //下拉默认id字段,如：id
        $this->selectIdField = 'id';
        //下拉列表查询时的字段，如：id,name，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，当前表可以不加
        $this->selectFields = '';
        //下拉列表父id字段，如：parent_id，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectParentId = 'parent_id';
        //下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOneParentWhere = [];
        //下拉列表查询排序，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOrder = '';
        //列表排序，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->sort = 'files.id desc';
        //父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，根据实际需求修改
        $this->parentField = '';
        //查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->oneParentWhere = [];
        //表格类型,table,treeTable
        $this->tableType = 'table';
        //树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为treeTable的时候会用到
        $this->treeTableGroupField = 'name';
        //需要合计的字段，如['显示在哪个字段','显示哪个字段的值']，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如['id'=>'admin.sex','money'=>admin.money']
        $this->totalRow = [];
        //设置主键
        $this->pk = 'id';
    }

    /**
     * 设置当前页面
     * @Author   July
     * @DateTime 2024-01-13T19:41:56+0800
     * @param    $table 表格
     */
    protected function buildPage(&$table = [])
    {
        //搜索
        $table->getSearch()
            ->show('text', 'name', '文件名')
            ->show('text', 'url', 'URL')
            ->show('select', 'type', '类型')->options(FilesModel::$file_type)
            ->show('datetime-local', 'create_time_start', '创建时间开始')
            ->show('datetime-local', 'create_time_end', '创建时间结束');

        //表格工具栏
        $table->getToolbar()
            ->addBtn()
            ->deleteBtn()
            ->refreshBtn();

        //左边树形列表
        $table->showLeftTree('category_id', '文件分类')->dataUrl(url('filesCategory/selectTree'));
        $table->tableTitle('文件列表');
        //表格数据
        $table->showCheckbox();
        $table->show('id', 'ID')->sort(true)->width(100);
        $table->show('name', '文件名')->edit('text')->sort(true)->width(350);
        $table->show('filesCategory.name', '文件分类')->sort(true)->width(150);
        $table->show('type', '类型')->sort(true)->width(100);
        $table->show('drive_id', '上传驱动')->sort(true)->width(110);
        $table->show('url', 'url')->width(500)->templet('return "<a target=\"_blank\" href=\""+val+"\">"+val+"</a>";');
        $table->show('create_time', '创建时间')->width(170)->sort(true);
        $table->show('update_time', '更新时间')->width(170)->sort(true);

        //表格右侧操作列
        $table->showRowHandleMenus()->width(130);
        $table->getTableRowBtns()
            ->editBtn()
            ->deleteBtn()
            ->viewBtn();

    }

    /**
     * 处理数据
     * 因为查询出来的数据可能需要二次处理
     * @Author   July
     * @DateTime 2024-01-13T19:44:46+0800
     * @param  array   &$data 查询出来的数据
     */
    protected function handleData(&$data = [])
    {
        foreach ($data as $dk => $dv) {
            $data[$dk]['type']     = FilesModel::$file_type[$dv['type']];
            $data[$dk]['drive_id'] = \july\julyadmin\uploaddrives\Drives::getDriveName($dv['drive_id']);
        }
    }

    /**
     * 处理查询条件
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param array $search  查询条件
     * @return  array $where
     */
    protected function filterWhere($search = [])
    {
        $where = [];
        foreach ($search as $k => $v) {
            if ($v === "") {
                continue;
            }
            switch ($k) {
                case "category_id":
                    $where[] = ['filesCategory.id', '=', $v];
                    break;
                case "type":
                    $where[] = ['files.type', '=', $v];
                    break;
                case "ext":
                    $where[] = ['', 'exp', \think\facade\Db::raw("FIND_IN_SET(files.ext, '{$v}')")];
                    break;
                case "name":
                    $where[] = ['files.name', 'like', '%' . $v . '%'];
                    break;
                case "url":
                    $where[] = ['files.url', 'like', '%' . $v . '%'];
                    break;
                case "create_time_start":
                    $where[] = ['files.create_time', '>=', $v];
                    break;
                case "create_time_end":
                    $where[] = ['files.create_time', '<=', $v];
                    break;
            }
        }

        return $where;
    }

    /**
     * 处理下拉列表查询条件
     * @Author   July
     * @DateTime 2024-01-13T19:47:05+0800
     * @param  array $where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere($where = [])
    {

        return $where;
    }

    /**
     * 处理合计行信息
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param    array                   $where    已经处理过的最终查询条件，可以自己覆盖，用来自己重新查询数据
     * @param    integer                 $limit    每页多少条
     * @param    string                  $sort     排序
     * @param    integer                 $page     第几页
     * @param    array                   $totalRow 已经查询出来的合计信息，可以自己覆盖返回
     * @return   array                   $totalRow 将处理过的最终信息返回
     */
    protected function filterTotalRow($where = [], $limit = 20, $sort = '', $page = 1, $totalRow = [])
    {
        return $totalRow;
    }

    /**
     * @Author   July
     * @DateTime 2024-01-13T19:49:03+0800
     * @param    Object                   &$form  form对象
     * @param    integer                  $isEdit 是否是编辑：0否，1是
     * @param    array                    &$data  当前这条数据的内容
     */
    protected function buildForm(&$form, $isEdit, &$data = [])
    {
        $form->show('text', 'name', '文件名');
        $form->show('file', 'url', '文件')->setSelectServerFile(false)->multiple();
        $form->show('select', 'type', '类型')->options(FilesModel::$file_type);
        $form->show('select', 'category_id', '文件分类')->dataUrl(url("filesCategory/selectPage"));

        if ($isEdit) {
            $form->show('html', 'create_time', '创建时间');
            $form->show('html', 'update_time', '更新时间');
        }
    }

    /**
     * 公共上传表单
     * 图片，文件上传组件和编辑器上传图片，视频，都会都会走这个方法
     * @param  integer $page   第几页
     * @param  integer $limit  每页多少条
     * @param  string  $sort   排序
     */
    public function commonUploadForm($page = 1, $limit = 20, $sort = '')
    {

        if (request()->ispost()) {
            $post_search = input('post.search', []);
            $get_search  = input('get.search', []);
            if (is_string($get_search)) {
                $get_search = json_decode($get_search, true) ?? [];
            }
            $search     = array_merge($post_search, $get_search);
            $where      = $this->filterWhere($search);
            $this->page = $page;
            if ($limit) {
                $this->limit = $limit;
            }

            if ($sort) {
                $this->sort = $sort;
            }
            if ($this->sort) {
                $this->sort = $this->sort;
            }
            $data = $this->buildDataList($where, $this->limit, $this->sort, $this->page, $this->total);
            return json($data);
        } else {
            $table   = new \july\julyadmin\builder\table\DataTable($this);
            $tableId = request()->controller() . request()->action() . "_table";
            //设置表格id
            $table->tableType('table')->tableId($tableId);
            //设置表格请求地址
            $table->datagridUrl($_SERVER['REQUEST_URI']);
            //隐藏默认工具栏
            $table->showDefaultToolbar(false);
            //搜索
            $table->getSearch()
                ->show('text', 'name', '文件名')
                ->show('text', 'url', 'URL')
                ->show('select', 'type', '类型')->options(FilesModel::$file_type)
                ->show('select', 'category_id', '文件分类')->dataUrl(url("filesCategory/selectPage"))
                ->show('datetime-local', 'create_time_start', '创建时间开始')
                ->show('datetime-local', 'create_time_end', '创建时间结束');

            //表格工具栏
            $table->getToolbar()
                ->addBtn()
                ->editBtn()
                ->viewBtn()
                ->deleteBtn()
                ->refreshBtn();

            //表格数据
            $table->showCheckbox();
            $table->show('name', '文件名')->sort(true)->width(100);
            $table->show('filesCategory.name', '文件分类')->sort(true)->width(150);
            $table->show('type', '类型')->sort(true)->width(100);
            $table->show('url', 'url')->templet('return "<a target=\"_blank\" href=\""+val+"\">"+val+"</a>";');
            $table->show('create_time', '创建时间')->sort(true)->width(180);

            $render  = $table->render();
            $builder = new \july\julyadmin\builder\Builder();

            //渲染顶部
            $builder->renderTop(false);

            $uploadMaxLength = input('uploadMaxLength', 10000);
            $uploadCallback  = input('uploadCallback', '');
            if (!$uploadCallback) {
                throw new \think\Exception("iframe父页面没有传递uploadCallback回调方法", 1);
            }
            echo <<<EOT

            <div class="container-fluid">
                <div class="card">
                    <div class="card-body" style="padding:5px 0px 5px 0px;">
                        {$render['html']}
                        {$render['script']}
                        <div style="text-align:center;">
                            <button type="button" onclick="confirmSelect(this);" style="margin-right:2px;" class="btn btn-primary">确认选择</button>
                        </div>
                    </div>
                </div>
            </div>

            <script>
                function confirmSelect(){
                    var data = layui.table.checkStatus('{$tableId}').data;
                    var urls = [];
                    var uploadMaxLength = {$uploadMaxLength};
                    if(data.length==0){
                        layer.msg('请选择文件！',{
                            icon:5,
                            time:2000,
                            shade:[0.6,'#000',false]
                        });
                        return false;
                    }
                    if(data.length>uploadMaxLength){
                        layer.msg('只能选择'+uploadMaxLength+'个文件！',{
                            icon:5,
                            time:2000,
                            shade:[0.6,'#000',false]
                        });
                        return false;
                    }else{
                        data.map(function(item){
                            urls.push({
                                name:item.name,
                                url:item.url
                            });
                        });
                    }
                    window.parent.{$uploadCallback}(urls);

                    //关闭父窗口
                    var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
                    parent.layer.close(index); //再执行关闭
                }
            </script>
EOT;
            //渲染底部
            $builder->renderBottom();
        }

    }

    /**
     * 保存
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param  integer $isEdit 是否是编辑 0否，1是
     */
    protected function save($isEdit)
    {
        $pk = input("get." . $this->getPk());

        $data = request()->only([
            'name',
            'url',
            'category_id',
            'type',
        ], 'post');

        try {
            $info = [
                'name|文件名'         => 'require',
                'url|文件URL'        => 'require',
                'category_id|文件分类' => 'require|number',
            ];
            validate($info)->check($data);
            $urls = array_filter(explode(',', $data['url']));
            foreach ($urls as $uk => $uv) {
                $data['url'] = $uv;
                $ext         = explode('.', $uv);
                $data['ext'] = $ext[count($ext) - 1];
                $find        = (new FilesModel())->where(['url' => $uv])->find();
                if ($find) {
                    $find->save($data);
                } else {
                    $this->success('上传失败');
                }
            }
            $this->success('上传成功');
        } catch (\think\exception\ValidateException $e) {
            $this->error($e->getError());
        }
    }
}
